import wx
from model import Body, BodyPart
from math import floor, ceil

class BodyEditor(wx.Control):

    def __init__(self, parent, body, selection=None):
        super(BodyEditor, self).__init__(parent, -1)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)

        self.body = body
        self.selection = selection
        self.windowPos = None
        self.windowZoom = 100.0
        self.b=wx.BitmapFromImage(wx.Image(r"/Users/robert/Desktop/test.png"))



    def setWindowPos(self, windowPos):
        if windowPos == self.windowPos: return
        self.windowPos = windowPos
        self.Refresh()


    def getWindowPos(self):
        if self.windowPos == None:
            winWidth, winHeight = self.GetClientSizeTuple()
            self.windowPos = (-winWidth/2 / self.getWindowZoom(),
                              -winHeight/2 / self.getWindowZoom() )
        return self.windowPos


    def setWindowZoom(self, windowZoom):
        if windowZoom == self.windowZoom: return
        self.windowZoom = windowZoom
        self.Refresh()


    def getWindowZoom(self):
        return self.windowZoom


    def setSelection(self, selection):
        if selection == self.selection: return
        self.selection = selection
        self.Refresh()


    def updateBody(self, body=None):
        if body != None:
            self.body = body
        self.Refresh()


    def drawBackground(self, dc, gc):
        dcWidth, dcHeight = dc.GetSizeTuple()
        gcZoom = self.getWindowZoom()
        gcX1, gcY1 = self.getWindowPos()
        gcX2 = gcX1 + dcWidth / gcZoom
        gcY2 = gcY1 + dcHeight / gcZoom

        dc.SetBrush(self.BGND_BRUSH)
        dc.DrawRectangle(0, 0, dcWidth, dcHeight)

        # draw grid
        for x in range(int(floor(gcX1)), int(ceil(gcX2))+1):
            dc.SetPen(self.GRD_PEN)
            dc.DrawLine((x-gcX1)*gcZoom, 0, (x-gcX1)*gcZoom, dcHeight)
            dc.SetPen(self.GRD_TENTH_PEN)
            for tenthX in range(1,10):
                dc.DrawLine((x+tenthX/10.0 - gcX1) * gcZoom, 0,
                            (x+tenthX/10.0 - gcX1) * gcZoom, dcHeight)
        
        for y in range(int(floor(gcY1)), int(ceil(gcY2))+1):
            dc.SetPen(self.GRD_PEN)
            dc.DrawLine(0, (y-gcY1)*gcZoom, dcWidth, (y-gcY1)*gcZoom)
            dc.SetPen(self.GRD_TENTH_PEN)
            for tenthY in range(1,10):
                dc.DrawLine(0,       (y+tenthY/10.0 - gcY1) * gcZoom,
                            dcWidth, (y+tenthY/10.0 - gcY1) * gcZoom)

        dc.SetPen(self.GRD_ORIGIN_PEN)
        dc.DrawLine(-gcX1*gcZoom, 0, -gcX1*gcZoom, dcHeight)
        dc.DrawLine(0, -gcY1*gcZoom, dcWidth, -gcY1*gcZoom)


    # draw images of bodyparts
    def drawBody(self, dc, gc, body=None):
        gcX1, gcY1 = self.getWindowPos()
        gcZoom = self.getWindowZoom()
        if body == None: body = self.body

        # iterate children behind this body element
        for child in body.iterChildrenBot2Top(skipBefore=True):
            self.drawBody(dc, gc, child)

        # draw bodypart of current body element
        savedTransformation = gc.GetTransform()
        bodyPart = body.getBodyPart()

        absX, absY = body.getAbsPos()
        x = (absX - gcX1) * gcZoom
        y = (absY - gcY1) * gcZoom
        gc.Translate(x, y)

        angle = body.getAbsAngle() + bodyPart.getAngle()
        gc.Rotate(angle)

        zoom = gcZoom * body.getAbsZoom() * bodyPart.getZoom()
        gc.Scale(zoom, zoom)
        if bodyPart.getMirrored():
            gc.Scale(-1, 1)

        bitmap = bodyPart.getCachedBitmap()
        centerX, centerY = bodyPart.getCenter()
        gc.DrawBitmap(bitmap, -centerX, -centerY,
                      bitmap.GetWidth(), bitmap.GetHeight() )

        gc.SetTransform(savedTransformation)

        # iterate children before this body element
        for child in body.iterChildrenBot2Top(skipBehind=True):
            self.drawBody(dc, gc, child)


    def drawEditHelpers(self, dc, gc, body=None, selected=False):
        gcZoom = self.getWindowZoom()
        gcX1, gcY1 = self.getWindowPos()
        if body == None: body = self.body
                
        savedTransformation = gc.GetTransform()

        if self.selection == body:
            selected=True
            ### initial point

        if selected == True
            pass all subpoints ####

        gc.SetTransform(savedTransformation)
        

    def OnPaint(self, ev):
        # get device context / graphics context
        dc = wx.PaintDC(self)
        gc = wx.GraphicsContext.Create(dc)

        # create colors
        self.BGND_BRUSH = wx.WHITE_BRUSH
        self.GRD_ORIGIN_PEN = wx.GREY_PEN
        self.GRD_PEN = wx.LIGHT_GREY_PEN
        self.GRD_TENTH_PEN = wx.Pen(wx.LIGHT_GREY, 1, wx.DOT)
        self.SEL_LINE_PEN = gc.CreatePen(wx.Pen(wx.Colour(255, 128, 128), width=2))
        self.SEL_POINT_PEN = gc.CreatePen(wx.Pen(wx.Colour(0, 127, 0, 128)))
        self.SEL_POINT_BRUSH = gc.CreateBrush(wx.Brush(wx.Colour(0, 255, 0)))

        # set 
        self.drawBackground(dc, gc)
        self.drawBody(dc, gc)
        self.drawEditHelpers(dc, gc)
        


if __name__ == "__main__":
    def img(name): return wx.Image(r"/Users/robert/Desktop/"+name)
    body = Body(BodyPart(img("test.png"), mirrored=True, angle=-1.5), children=
                [Body(BodyPart(img("test2.png")), pos=(0.1,0.5))]
                )
                    
                
    
    app = wx.App(redirect=False)
    frame = wx.Frame(None, -1, "Test BodyEditor")
    bodyEditor = BodyEditor(frame, body)

    import wx.py
    wx.py.shell.ShellFrame(pos=(500,0)).Show()
    frame.Show()
    app.MainLoop()
